package com.pubinfo.passbook.data.service.impl;

import api.VoucherFileUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pansoft.xbrl.xbrljson.reader.impl.BaseXbrlReader;
import com.pubinfo.passbook.common.entity.*;
import com.pubinfo.passbook.common.exception.ServiceException;
import com.pubinfo.passbook.common.mapper.TFileInfoMapper;
import com.pubinfo.passbook.common.model.dto.file.FileInfoParam;
import com.pubinfo.passbook.common.model.dto.open.InvoiceParam;
import com.pubinfo.passbook.common.service.master.TNewSourceInvoiceService;
import com.pubinfo.passbook.common.service.master.TNewSourceInvoiceTollService;
import com.pubinfo.passbook.data.service.TFileInfoService;
import com.pubinfo.passbook.data.service.VoucherFileService;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;
import org.dom4j.DocumentException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.zip.ZipException;

@Service
public class VoucherFileServiceImpl implements VoucherFileService
{

    @Autowired
    TFileInfoMapper tFileInfoMapper;
    @Autowired
    TNewSourceInvoiceService tNewSourceInvoiceService;
    @Autowired
    com.pubinfo.passbook.common.master.service.TNewSourceInvoiceItemService tNewSourceInvoiceItemService;
    @Autowired
    TNewSourceInvoiceTollService tNewSourceInvoiceTollService;
    @Autowired
    TFileInfoService tFileInfoService;

    @Override
    public JSONObject invoiceOdf2Json(String fileId) throws Exception {

        FileInfoParam fileInfoParam=tFileInfoMapper.selectFileInfoParam(fileId);

        if(!fileInfoParam.getContentType().equals("application/ofd"))
        {
            throw new ServiceException("文件非版式文件");
        }

        String fileName=fileInfoParam.getName().replaceAll("\\.ofd","");
        String filePath=fileInfoParam.getPath().replaceAll(fileName+"\\.ofd","");
        String invoiceType=fileInfoParam.getFplx();
        String type=null;

        if(invoiceType.equals("ZZS_DZFP")) {
            //电子普票
            type="inv_ord_issuer";
        }
        else if(invoiceType.equals("ZZS_DZZP")) {
            //电子专票
            type="inv_spcl_issuer";
        }
        else if(invoiceType.equals("DZ_TXFFP")) {
            //通行费发票
            type="inv_tlf_issuer";
        }
        else {
            //其他暂时没版式文件同步
            throw new ServiceException("暂不支持此类发票解析");
        }

        return ofd2Json(filePath,fileName,type);
    }

    @Override
    public JSONObject ofd2Json(String filePath,String fileName, String type) throws Exception {
        //将odf转换成xml格式
        VoucherFileUtil.extractXBRLFromOFD(filePath+fileName+".ofd",filePath+fileName+".xbrl");
        //读取xml之后转换成json
        BufferedReader br = new BufferedReader(new FileReader(filePath+fileName+".xbrl"));//构造一个BufferedReader类来读取文件
        String s = null;
        int sum=0;
        StringBuffer stringBuffer=new StringBuffer();
        while((s = br.readLine())!=null){//使用readLine方法，一次读一行
            stringBuffer.append(s);
        }
        br.close();
        //删除xbrl文件
        File file = new File(filePath+fileName+".xbrl");
        FileSystemUtils.deleteRecursively(file);
        return VoucherFileUtil.xbrl2Json(stringBuffer.toString(),type);
    }

    @Override
    public void getOfdXml(HttpServletRequest request, HttpServletResponse response, TFileInfo tFileInfo) throws Exception {
        try
        {
            VoucherFileUtil.extractXBRLFromOFD(tFileInfo.getPath(),tFileInfo.getPath().substring(0,tFileInfo.getPath().lastIndexOf("."))+".xml");
        }catch (ZipException e){
            VoucherFileUtil.extractXBRLFromPDF(tFileInfo.getPath(),tFileInfo.getPath().substring(0,tFileInfo.getPath().lastIndexOf("."))+".xml");
        }
        response.setCharacterEncoding(request.getCharacterEncoding());
        response.setContentType("application/xml");
        FileInputStream fis = null;
        File file = new File(tFileInfo.getPath().substring(0,tFileInfo.getPath().lastIndexOf("."))+".xml");
        try {
            fis = new FileInputStream(file);
            response.setHeader("Content-Disposition", "attachment; filename=\"" + tFileInfo.getName().substring(0,tFileInfo.getName().lastIndexOf("."))+".xml" + "\"");
            IOUtils.copy(fis, response.getOutputStream());
            response.flushBuffer();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                    FileUtils.deleteQuietly(file);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public TNewSourceInvoice ofdAnalysis(String filePath, String fileName, Date machiningDate) throws Exception {
        VoucherFileUtil.extractXBRLFromOFD(filePath+fileName+".ofd",filePath+fileName+".xml");
        BufferedReader br = new BufferedReader(new FileReader(filePath+fileName+".xml"));//构造一个BufferedReader类来读取文件
        String s = null;
        int sum=0;
        StringBuffer stringBuffer=new StringBuffer();
        while((s = br.readLine())!=null){//使用readLine方法，一次读一行
            stringBuffer.append(s);
        }
        br.close();
        JSONObject jsonObject=null;
        jsonObject =  new BaseXbrlReader().readXbrlDataWithXml(stringBuffer.toString().replaceAll("&","&amp;"));
        System.out.println(jsonObject);
        TNewSourceInvoice invoice=JSONObject.toJavaObject(jsonObject,TNewSourceInvoice.class);
        invoice.setDataJson(jsonObject);
        invoice.setDateOfMachining(machiningDate);
        if(invoice.getInformationOfTaxableGoodsOrServicesDetailItemsTuple()!=null)
        {
            invoice.getInformationOfTaxableGoodsOrServicesDetailItemsTuple().stream().forEach(tNewSourceInvoiceItem -> tNewSourceInvoiceItem.setUniqueCodeOfInvoice(invoice.getUniqueCodeOfInvoice()));
        }
        if(invoice.getInformationOfTollFeeDetailItemsTuple()!=null)
        {
            invoice.getInformationOfTollFeeDetailItemsTuple().stream().forEach(tNewSourceInvoiceToll -> tNewSourceInvoiceToll.setUniqueCodeOfInvoice(invoice.getUniqueCodeOfInvoice()));
        }
        System.err.println(JSONObject.toJSON(invoice));
        tNewSourceInvoiceService.saveOrUpdate(invoice);


        //先将所有相关项目删除
        QueryWrapper<TNewSourceInvoiceItem> itemQueryWrapper = new QueryWrapper<>();
        itemQueryWrapper.eq("unique_code_of_invoice", invoice.getUniqueCodeOfInvoice());
        tNewSourceInvoiceItemService.remove(itemQueryWrapper);

        QueryWrapper<TNewSourceInvoiceToll> tollQueryWrapper = new QueryWrapper<>();
        tollQueryWrapper.eq("unique_code_of_invoice", invoice.getUniqueCodeOfInvoice());
        tNewSourceInvoiceTollService.remove(tollQueryWrapper);

        //保存项目及通行费项目
        tNewSourceInvoiceItemService.saveBatch(invoice.getInformationOfTaxableGoodsOrServicesDetailItemsTuple());
        tNewSourceInvoiceTollService.saveBatch(invoice.getInformationOfTollFeeDetailItemsTuple());
        return invoice;
    }

    @Override
    public void getInvoiceFile(HttpServletRequest request, HttpServletResponse response, InvoiceParam invoiceParam) throws Exception {

        String fileId=tFileInfoMapper.selectFileIdByFpdmAndFphm(invoiceParam.getCodeOfInvoice(),invoiceParam.getNumberOfInvoice());
        if(fileId==null)
        {
            fileId=tFileInfoMapper.selectPassbookFileIdByInvoice(invoiceParam.getCodeOfInvoice(),invoiceParam.getNumberOfInvoice());
            if(fileId==null)
            {
                throw new ServiceException("发票不存在");
            }
        }
        if(invoiceParam.getType()==1)
        {
            tFileInfoService.acctDownload(request, response,fileId);

        }else if(invoiceParam.getType()==2)
        {
            getOfdXml(request, response,tFileInfoMapper.selectById(fileId));
        }
        else
        {
            throw new ServiceException("type输入错误");
        }
    }


}
